package com.polaris.live.common

import assertk.assertions.isEqualTo
import assertk.assertions.isNotNull
import com.polaris.live.common.util.JsonUtils
import org.junit.Test

/**
 * JsonUtilsTest
 *
 * @author Created by lucas on 2023/11/4 10:14
 */
class JsonUtilsTest {

    @Test
    fun testToJsonAny() {
        val map = mapOf(
            "key1" to "value1",
            "key2" to JsonBean(1, "2", "notNull")
        )

        JsonUtils.toJson(map)
            .toAssertThat()
            .isEqualTo("""{"key1":"value1","key2":{"int":1,"string":"2","nullable":"notNull"}}""")
    }

    @Test
    fun testToJson() {
        JsonUtils.toJson(JsonBean(1, "2", "notNull"))
            .toAssertThat()
            .isEqualTo("""{"int":1,"string":"2","nullable":"notNull"}""")

        JsonUtils.toJson(JsonBean(1, "2"))
            .toAssertThat()
            .isEqualTo("""{"int":1,"string":"2"}""")
    }

    @Test
    fun testFromJson() {
        JsonUtils.fromJson<JsonBean>("""{"int":1,"string":"2","nullable":"notNull"}""")
            .toAssertThat()
            .isEqualTo(JsonBean(1, "2", "notNull"))

        JsonUtils.fromJson<JsonBean>("""{"int":1,"string":"2"}""")
            .toAssertThat()
            .isEqualTo(JsonBean(1, "2"))
    }

    @Test
    fun testReadJsonObject() {
        val json = genJson()

        var string: String? = null
        var beanName: String? = null
        JsonUtils.readJsonObject(json) {
            if (name == "bean") {
                nextObject {
                    if (it.name == "string") {
                        string = it.getString()
                    }
                }
            } else if (name == "name") {
                beanName = getString()
            }
        }

        string.toAssertThat()
            .isNotNull()
            .isEqualTo("2")

        beanName.toAssertThat()
            .isNotNull()
            .isEqualTo("name1")
    }

    @Test
    fun testReadJsonArray() {
        val list = listOf(
            NestedJsonBean(
                "name1",
                JsonBean(1, "2", "notNull1")
            ),
            NestedJsonBean(
                "name2",
                JsonBean(3, "4", "notNull2")
            )
        )
        val json = JsonUtils.toJson(list)

        var string1: String? = null
        var beanName1: String? = null
        var string2: String? = null
        var beanName2: String? = null
        JsonUtils.readJsonArray(json) {
            if (index == 0) {
                nextObject {
                    if (it.name == "bean") {
                        it.nextObject { inner ->
                            if (inner.name == "string") {
                                string1 = inner.getString()
                            }
                        }
                    } else if (it.name == "name") {
                        beanName1 = it.getString()
                    }
                }
            } else if (index == 1) {
                nextObject {
                    if (it.name == "bean") {
                        it.nextObject { inner ->
                            if (inner.name == "string") {
                                string2 = inner.getString()
                            }
                        }
                    } else if (it.name == "name") {
                        beanName2 = it.getString()
                    }
                }
            }
        }

        string1.toAssertThat()
            .isNotNull()
            .isEqualTo("2")
        string2.toAssertThat()
            .isNotNull()
            .isEqualTo("4")

        beanName1.toAssertThat()
            .isNotNull()
            .isEqualTo("name1")
        beanName2.toAssertThat()
            .isNotNull()
            .isEqualTo("name2")
    }

    @Test
    fun testReadStringFromJsonObject() {
        val json = genJson()

        JsonUtils.readStringFromJsonObject(json, "name")
            .toAssertThat()
            .isNotNull()
            .isEqualTo("name1")
    }

    private fun genJson(): String {
        val bean = NestedJsonBean(
            "name1",
            JsonBean(1, "2", "notNull")
        )
        return JsonUtils.toJson(bean)
    }
}

data class JsonBean(
    val int: Int,
    val string: String,
    val nullable: String? = null
)

data class NestedJsonBean(
    val name: String,
    val bean: JsonBean
)